from django.contrib import auth as django_auth
from django.db.models import Q
from django.shortcuts import get_object_or_404
from rest_framework import exceptions
from rest_framework import generics
from rest_framework import permissions
from rest_framework import response
from rest_framework import views
from rest_framework.authtoken.models import Token
import rest_framework as drf
from . import serializers
from myproject import models as models_myproject
from course import models as models_course
from account import models as models_account
import django_filters.rest_framework
from yuncoding import settings
import os
import subprocess
import uuid


class MyProjectCreateView(generics.CreateAPIView):
    permission_classes = (permissions.IsAuthenticated,)
    serializer_class=serializers.ProjectSerializer
    def post(self,request):
        try:
            account = request.user.account
            programming_language = request.data.get('programming_language')
            project_name = request.data.get('project_name')
            ti_id=request.data.get('ti_id')
            type= str(request.data.get('type'))
        except:
            raise drf.serializers.ValidationError('未找到全不参数')

        type_eu = ['0', '1', '2',]
        if not type in type_eu:
            raise drf.serializers.ValidationError('type未找到')

        project_list=models_myproject.Project.objects.filter(account_id=account.id)
        for project_item in project_list:
            if project_item.project_name == project_name:
                raise drf.serializers.ValidationError('项目名重复')

        if int(ti_id) != -1:
            if type == '0':
                try:
                    validate_1 = models_course.Ti.objects.get(id=ti_id)
                except:
                    raise drf.serializers.ValidationError('Error:未找到该题目')
                try:
                    validate_4 = models_course.MyAssignment.objects.get(account_id=account.id, ti_id=ti_id)
                    if validate_4.project_id != -1:
                        data = {'detail': '该题已存在对应的项目', 'project_id': validate_4.project_id }
                        return response.Response(data)
                except:
                    raise drf.serializers.ValidationError('Error:未找到该题目对应的作业')
                if account.role == '1':
                    try:
                        models_course.StudentCourse.objects.get(account_id=account.id,
                                                                course_id=validate_1.course_id, status='1')
                    except:
                        raise drf.serializers.ValidationError('Error:未找到该题目对应的有效课程')
                elif account.role == '2':
                    try:
                        models_course.Course.objects.get(id=validate_1.course_id,
                                                         account_id=account.id, status='1')
                    except:
                        raise drf.serializers.ValidationError('Error:未找到该题目对应的有效课程')

        if account.role == '1':
            submited = False
        elif account.role == '2':
            submited = True

        # 为项目自动创建一个Main文件
        if programming_language == 'C':
            file_name = 'main.c'
            code = '#include <stdio.h>\n\nint main() \n{\n    printf("hello world!");\n    return 0;\n}\n'
        elif programming_language == 'C++':
            file_name = 'main.cpp'
            code = '#include <iostream>\n\nusing namespace std;\n\nint main() \n{\n    cout << "hello world!" << endl;\n    return 0;\n}\n'
        elif programming_language == 'Java':
            file_name = 'main.java'
            code = 'class Untitled {\n    public static void main(String[] args) {\n\tSystem.out.println("hello https://tool.lu/");\n    }\n}\n'
        elif programming_language == 'Fortran':
            file_name = 'main.f95'
            code = 'program main\nimplicit none\n    write(*,*) "Hello World!"\nend\n'
        else:
            raise drf.serializers.ValidationError('Error:未能找到该类型对应的main文件')


        project = models_myproject.Project.objects.create(
            account_id=account.id,
            programming_language=programming_language,
            project_name=project_name,
            received=True,
            ti_id=ti_id,
            submited=submited)
        project_detail = models_myproject.ProjectDetail.objects.create(
            project_id=project.id,
            file_name=file_name,
            code=code, )
        if int(ti_id) != -1:
            try:
                assignment_id = models_course.Ti.objects.get(id=ti_id)
                if type == '0':  # 课后作业
                    print(str(account.id)+'  -----' + str(ti_id))
                    my_assignment = models_course.MyAssignment.objects.get(account_id=account.id, ti_id=ti_id)
                    my_assignment.project_id = project.id
                    my_assignment.save()
            except:
                raise drf.serializers.ValidationError('Error:修改作业项目ID失败')

        project_data = {}
        project_data['account_id'] = account.id
        project_data['programming_language'] = programming_language
        project_data['project_name'] = project_name
        project_data['file_name'] = file_name
        project_data['code'] = code
        project_data['project_id'] = project.id
        project_data['project_detail_id']=project_detail.id

        return response.Response(project_data)


class MyProjectReceiveView(views.APIView):
    permission_classes = (permissions.IsAuthenticated,)

    def post(self,request):
        project_id = request.data.get('project_id')
        account=request.user.account
        try:
            project = models_myproject.Project.objects.get(id=project_id,
                                                           account_id=account.id,
                                                           status='1')
        except:
            raise drf.serializers.ValidationError('未找到该项目')

        project_list = models_myproject.Project.objects.filter(account_id=account.id,received=True)
        for project_item in project_list:
            if (project_item.project_name == project.project_name) and (project.id != project_item.id):
                raise drf.serializers.ValidationError('项目名重复')

        project.received=True
        project.save()

        return response.Response('接收成功')



class MyProjectOpenView(views.APIView):
    permission_classes = (permissions.IsAuthenticated,)

    def get(self, request):
        project_id = request.GET.get('project_id')
        account=request.user.account
        try:
            if  account.role == '1':
                project = models_myproject.Project.objects.get(id=project_id,account_id=account.id,status='1')
            elif account.role == '2':
                try:
                    project = models_myproject.Project.objects.get(id=project_id,account_id=account.id,status='1')
                except:
                    project = models_myproject.Project.objects.get(id=project_id,
                                                                   submited=True,
                                                                   status='1')
                    #暂时先取消对学生是否属于老师课程的判断
                    #studentcourse = models_course.StudentCourse.objects.get(account_id=project.account_id)
                    #course = models_course.Course.objects.get(account_id=account.id, id=studentcourse.course_id)
            files=models_myproject.ProjectDetail.objects.filter(project_id =project_id)
        except:
            raise drf.serializers.ValidationError('ERROR:未找到该项目')

        myPro=serializers.ProjectOpenSerializer.Struct
        myPro.project_id=project.id
        myPro.account_id=account.id
        myPro.programming_language=project.programming_language
        myPro.project_name=project.project_name
        myPro.files=[]
        try:
            for file_item in files:
                item = serializers.ProjectFileSerializer.Struct(file_item.id,
                                                                file_item.file_name,
                                                                file_item.code)
                myPro.files.append(item)
        except:
            raise drf.serializers.ValidationError('ERROR:获取题目时发生错误')
        data = serializers.ProjectOpenSerializer(myPro).data
        return response.Response(data)



'''class MyProjectAllListView(generics.ListAPIView):
    permission_classes = (permissions.IsAuthenticated,)
    serializer_class = serializers.ProjectAllProjectSerializer

    def get_queryset(self):
        account_id=self.request.user.account.id
        queryset = models_myproject.Project.objects.filter(account_id=account_id,status='1')
        return queryset'''

class MyProjectAllListView(views.APIView):
    permission_classes = (permissions.IsAuthenticated,)
    serializer_class = serializers.ProjectAllProjectSerializer

    def get(self, request):
        account=request.user.account
        project_list=models_myproject.Project.objects.filter(account_id=account.id,status='1')

        data=serializers.ProjectAllProjectSerializer(project_list,many=True).data
        return response.Response(data)



class MyprojectSaveView(views.APIView):
    permission_classes = (permissions.IsAuthenticated,)

    def post(self, request):
        project_id = request.data.get('myproject_id')
        account=request.user.account
        programming_language=request.data.get('programming_language')
        project_name = request.data.get('project_name')
        files = request.data.get('files')

        try:
            if account.role =='1':
                project = models_myproject.Project.objects.get(id=project_id, account_id=account.id, status='1')
            elif account.role == '2':
                project = models_myproject.Project.objects.get(id=project_id, status='1')
        except:
            raise drf.serializers.ValidationError('ERROR:项目ID错误'+str(project_id))
        project.programming_language=programming_language
        project.project_name=project_name
        project.save()
        for file_item in files:
            try:
                project_detail = models_myproject.ProjectDetail.objects. \
                    get(id=file_item['project_detail_id'], project_id=project_id)
            except:
                raise drf.serializers.ValidationError('ERROR:文件ID错误')
            project_detail.file_name = file_item['file_name']
            project_detail.code = file_item['code']
            project_detail.save()

        return response.Response("保存成功")


class MyProjectFileView(views.APIView):
    permission_classes = (permissions.IsAuthenticated,)
    def post(self, request):
        project_id = request.data.get('project_id')
        file_name=request.data.get('file_name')
        project_detail_id = request.data.get('project_detail_id')
        action_type=str(request.data.get('action_type'))
        account=request.user.account

        # 通过查询来判断是否是我的项目
        try:
            if  account.role == '1':
                project = models_myproject.Project.objects.get(account_id=account.id, id=project_id,status='1')
            elif account.role == '2':
                project = models_myproject.Project.objects.get(id=project_id, status='1')
        except:
            raise drf.serializers.ValidationError('ERROR:项目ID错误')

        #对操作的文件名进行一些必要的判断
        main_eu = ['main.c', 'main.cpp', 'main.java', 'main.f95']
        if file_name == None:
            raise drf.serializers.ValidationError('file_name为null')
        if (file_name in main_eu):
            raise drf.serializers.ValidationError('main文件不允许删除或者创建')


        if action_type == '0':
            try:
                project_detail=models_myproject.ProjectDetail.objects.get(id=project_detail_id,project_id=project_id)
                project_detail.delete()
                data={'detail':'删除成功'}
                return response.Response(data)
            except:
                raise drf.serializers.ValidationError('ERROR:删除文件失败')
        elif action_type == '1':
            # 去除file_name前后空格
            file_name_tmp = file_name.strip()
            file_name = file_name_tmp

            # 判断后缀名
            file_extension = os.path.splitext(file_name)[1].lower()
            print(file_extension + '     ' + file_name)
            if project.programming_language == 'C':
                if file_extension != '.c':
                    raise drf.serializers.ValidationError('文件名后缀错误')
            elif project.programming_language == 'C++':
                if file_extension != '.cpp':
                    raise drf.serializers.ValidationError('文件名后缀错误')
            elif project.programming_language == 'Java':
                if file_extension != '.java':
                    raise drf.serializers.ValidationError('文件名后缀错误')
            elif project.programming_language == 'Fortran':
                if file_extension != '.f95':
                    raise drf.serializers.ValidationError('文件名后缀错误')
            else:
                raise drf.serializers.ValidationError('Error:该项目语言类型未找到')

            # 判断文件是否重复
            project_detail_list = models_myproject.ProjectDetail.objects.filter(project_id=project_id)
            for item in project_detail_list:
                if os.path.splitext(item.file_name)[0] == os.path.splitext(file_name)[0]:
                    raise drf.serializers.ValidationError('Error:文件名重复')

            try:
                obj = models_myproject.ProjectDetail(project_id=project_id,
                                                              file_name=file_name,
                                                              code='')
                obj.save()
                data={'detail':'创建成功','project_detail_id':obj.id}
                return response.Response(data)
            except:
                raise drf.serializers.ValidationError('ERROR:删除文件失败')
        else:
            raise drf.serializers.ValidationError('ERROR:操作类型不存在')


def creatProject(project_id,account_id,target_account_id,received,submited):
    try:
        project1 = models_myproject.Project.objects.get(id=project_id, account_id=account_id,status='1')
        project1.pk = None
        project1.account_id = target_account_id
        project1.received = received
        project1.submited=submited
        project1.save()

        file_list = models_myproject.ProjectDetail.objects.filter(project_id=project_id)
        for file in file_list:
            file.pk = None
            file.project_id = project1.id
            file.save()
    except:
        raise drf.serializers.ValidationError("创建项目失败")


class MyProjectSendView(generics.CreateAPIView):
    permission_classes = (permissions.IsAuthenticated,)
    def post(self, request):
        course_id = request.data.get('course_id')
        send_type = request.data.get('send_type')
        target_account_id = request.data.get('target_account_id')
        project_id = request.data.get("project_id")
        account=request.user.account

        send_type_eu = ['0', '1', '2' ]
        if not send_type in send_type_eu:
            raise drf.serializers.ValidationError('send_type未找到')

        try:
            project=models_myproject.Project.objects.get(id=project_id,account_id=account.id,status='1')
            if account.role == '1':
                validate1=models_course.StudentCourse.objects.get(account_id=account.id,course_id=course_id)
            elif account.role == '2':
                validate2=models_course.Course.objects.get(id = course_id,account_id = account.id)
            if target_account_id != -1:
                validate2 = models_course.StudentCourse.objects.get(account_id=target_account_id, course_id=course_id)
        except:
            raise drf.serializers.ValidationError('ERROR:参数查询错误')

        if  account.role == '1':#学生
            if  send_type == '0':#发送给老师
                try:
                    detail=models_course.MyAssignment.objects.get(account_id=account.id,project_id=project_id)
                    detail.submited=True
                    detail.save()
                    project.submited=True
                    project.save()
                except:
                    teacher_id = models_course.Course.objects.get(id=course_id).account_id
                    creatProject(project_id, account.id, teacher_id, False,True)
            elif send_type == '1':#发送给某一同学

                creatProject(project_id,account.id,target_account_id,False,False)
            elif send_type == '2':# 发送课堂作业
                try:
                    course = models_course.Course.objects.get(id=course_id)
                    ti = models_course.Ti.objects.get(assignment_id=course.assignment_id)
                except:
                    raise drf.serializers.ValidationError('ERROR:课堂作业查询错误')

                #更新课堂作业，有则更新，无则创建
                try:
                    assignment_detail=models_course.MyAssignment.get(account_id=account.id,
                                                                     ti_id=ti.id)
                    assignment_detail.project_id=project_id
                    assignment_detail.submited=True
                    assignment_detail.compile_successed=project.compile_successed
                    assignment_detail.save()
                except:
                    myassignment_2 = models_course.MyAssignment.objects.create(
                        account_id=account.id,
                        assignment_id=course.assignment_id,
                        ti_id=ti.id,
                        project_id=project_id,
                        submited=True,
                        compile_successed=project.compile_successed
                    )
                    project.submited = True
                    project.save()
            else:
                raise drf.serializers.ValidationError('ERROR:send_type错误')
        elif account.role == '2':#老师
            if  send_type == '0':#发送给班级的所有学生

                student_id_list=models_course.StudentCourse.objects.filter(course_id=course_id)
                for student_id_item in student_id_list:
                    creatProject(project_id,account.id,student_id_item.account_id,False,False)

            elif send_type == '1':#发送给某一同学

                creatProject(project_id,account.id, target_account_id,False,False)

            else:
                raise drf.serializers.ValidationError('ERROR:send_type错误')
        else:
            raise drf.serializers.ValidationError('ERROR:用户角色发生错误')

        data = {'detail': '发送成功'}
        return response.Response(data)

class MyProjectCompileView(views.APIView):
    permission_classes = (permissions.IsAuthenticated,)
    def post(self, request):
        project_id = request.data.get('project_id')
        account=request.user.account
        try:
            if  account.role == '1':
                project=models_myproject.Project.objects.get(account_id=account.id,id=project_id,status='1')
            elif account.role == '2':
                project = models_myproject.Project.objects.get( id=project_id, status='1')
        except:
            raise drf.serializers.ValidationError('ERROR:未能找到该项目')

        #生成文件
        path= settings.BASE_DIR + '/media/Project/account_'+str(account.id)+'/'+ str(project_id)+'_project/'
        isExists = os.path.exists(path)
        if not isExists:
            os.makedirs(path)
        os.chdir(path)

        pars = ''
        file_list=models_myproject.ProjectDetail.objects.filter(project_id=project_id)
        for file_item in file_list:
            fh = open(file_item.file_name, 'w')
            fh.write(file_item.code)
            fh.close()
            pars = pars + '"' + file_item.file_name + '"' + ' '

        if project.programming_language == 'C':
            cmd='gcc ' + pars + ' -lm -o project'
        elif project.programming_language == 'C++':
            cmd = 'g++ ' + pars + '-o project'
        elif project.programming_language == 'Java':
            pass
        elif project.programming_language == 'Fortran':
            cmd = 'gfortran ' + pars + '-o project'
        else:
            raise drf.serializers.ValidationError('Error:未能找到该类型对应的语言类型')

        print(cmd)
        compile_output=subprocess.getstatusoutput(cmd)

        data={}
        if  compile_output[0] == 0:
            project.compile_successed = True
            project.save()
            # 修改myassignment中的编译状态
            myassmignment_list = models_course.MyAssignment.objects.filter(project_id=project_id)
            for myassmignment in myassmignment_list:
                myassmignment.compile_successed = True
                myassmignment.save()
            data['success'] = '1'
        else:
            data['success'] = '0'

        data['path'] = str('/account_'+str(account.id)+'/'+ str(project_id)+'_project/project')
        data['data'] = str(compile_output[1]).replace('\n','\r\n')
        return response.Response(data)



class MyProjectUpdateView(views.APIView):
    permission_classes = (permissions.IsAuthenticated,)
    def post(self, request):
        project_id = request.data.get('project_id')
        project_status=request.data.get('project_status')
        account=request.user.account
        try:
            project=models_myproject.Project.objects.get(account_id=account.id,id=project_id)
        except:
            raise drf.serializers.ValidationError('ERROR:未能找到该课程')

        if  project_status == '0':
            project.status ='0'
        elif project_status == '1':
            project.status = '1'
        project.save()

        data = {'detail': '修改成功'}
        return response.Response(data)



class MyProjectGuestView(views.APIView):

    def post(self, request):
        programming_language=request.data.get('programming_language')
        project_name = request.data.get('project_name')
        files = request.data.get('files')
        # 生成文件
        uuid_num=str(uuid.uuid1())
        path = settings.BASE_DIR + '/media/Project/Temp/project_'+ uuid_num +'/'
        isExists = os.path.exists(path)
        if not isExists:
            os.makedirs(path)
        os.chdir(path)

        pars = ''

        for file_item in files:
            fh = open( file_item['file_name'], 'w')
            fh.write(file_item['code'])
            fh.close()
            pars = pars  + '"' + file_item['file_name'] + '"' + ' '

        if programming_language == 'C':
            cmd='gcc ' + pars + ' -lm -o project'
        elif programming_language == 'C++':
            cmd = 'g++ ' + pars + '-o project'
        elif programming_language == 'Java':
            pass
        elif programming_language == 'Fortran':
            cmd = 'gfortran ' + pars + '-o project'
        else:
            raise drf.serializers.ValidationError('Error:未能找到该类型对应的语言类型')

        compile_output = subprocess.getstatusoutput(cmd)

        data = {}
        if compile_output[0] == 0:
            data['success'] = '1'
        else:
            data['success'] = '0'
        data['data'] = str(compile_output[1]).replace('\n','\r\n')
        data['path'] = str( '/Temp/project_'+ uuid_num +'/project')

        return response.Response(data)


class MyProjectGuestCreateView(generics.CreateAPIView):
    serializer_class=serializers.ProjectSerializer
    def post(self,request):
        programming_language = request.data.get('programming_language')
        project_name = request.data.get('project_name')

        programming_language_eu = ['C', 'C++', 'Java','Fortran']
        if not programming_language in programming_language_eu:
            raise drf.serializers.ValidationError('暂不支持该语言类型')


        # 为项目自动创建一个Main文件
        if programming_language == 'C':
            file_name = 'main.c'
            code = '#include <stdio.h>\n\nint main() \n{\n    printf("hello world!");\n    return 0;\n}\n'
        elif programming_language == 'C++':
            file_name = 'main.cpp'
            code = '#include <iostream>\n\nusing namespace std;\n\nint main() \n{\n    cout << "hello world!" << endl;\n    return 0;\n}\n'
        elif programming_language == 'Java':
            file_name = 'main.java'
            code = 'class Untitled {\n    public static void main(String[] args) {\n\tSystem.out.println("hello https://tool.lu/");\n    }\n}\n'
        elif programming_language == 'Fortran':
            file_name = 'main.f95'
            code = 'program main\nimplicit none\n    write(*,*) "Hello World!"\nend\n'
        else:
            raise drf.serializers.ValidationError('Error:未能找到该类型对应的main文件')


        project_data = {}
        project_data['programming_language'] = programming_language
        project_data['project_name'] = project_name
        project_data['file_name'] = file_name
        project_data['code'] = code

        return response.Response(project_data)